package com.github.ilioili.justdoit.util;

import com.github.ilioili.justdoit.common.config.UserInfo;
import com.github.ilioili.justdoit.util.sql.DbUtil;
import com.qiniu.android.common.Zone;
import com.qiniu.android.http.ResponseInfo;
import com.qiniu.android.storage.Configuration;
import com.qiniu.android.storage.UpCompletionHandler;
import com.qiniu.android.storage.UpProgressHandler;
import com.qiniu.android.storage.UploadManager;
import com.qiniu.android.storage.UploadOptions;
import com.qiniu.android.utils.UrlSafeBase64;
import com.taihe.template.base.util.LogUtil;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

/**
 * Created by User on 16/6/21.
 */
public class QiniuUtil {
    public static final String ACCESS_KEY = "QXp3l8f5xJ-nddicC_6LEJesYipTswQyZZPw37r1";
    private static Configuration config = new Configuration.Builder()
            .chunkSize(256 * 1024)  //分片上传时，每片的大小。 默认 256K
            .putThreshhold(512 * 1024)  // 启用分片上传阀值。默认 512K
            .connectTimeout(10) // 链接超时。默认 10秒
            .responseTimeout(60) // 服务器响应超时。默认 60秒
//                .recorder(recorder)  // recorder 分片上传时，已上传片记录器。默认 null
//                .recorder(recorder, keyGen)  // keyGen 分片上传时，生成标识符，用于片记录器区分是那个文件的上传记录
            .zone(Zone.zone0) // 设置区域，指定不同区域的上传域名、备用域名、备用IP。默认 Zone.zone0
            .build();
    // 重用 uploadManager。一般地，只需要创建一个 uploadManager 对象
    private static UploadManager uploadManager = new UploadManager(config);

    private static final String HMAC_SHA1_ALGORITHM = "HMAC-SHA1";
    public static final String SECRET_KEY = "w3ykWkLQpwUwDDAgaAzsMKexVnB-qI8olG2xUnCJ";

    public static String hmacDigest(String msg, String keyString, String algo) {
        String digest = null;
        try {
            SecretKeySpec key = new SecretKeySpec((keyString).getBytes("UTF-8"), algo);
            Mac mac = Mac.getInstance(algo);
            mac.init(key);

            byte[] bytes = mac.doFinal(msg.getBytes("ASCII"));
            return UrlSafeBase64.encodeToString(bytes);

        } catch (UnsupportedEncodingException e) {
        } catch (InvalidKeyException e) {
        } catch (NoSuchAlgorithmException e) {
        }
        return digest;
    }

    public static void uploadDbFile(final Callback callback) {
        File data = new File(DbUtil.getDb().getPath());
        JSONObject jsonObject = new JSONObject();
        try {
            jsonObject.put("scope", "justdoit-dbs:" + UserInfo.getUserId());
            jsonObject.put("deadline", System.currentTimeMillis() / 1000 + 3600);
            jsonObject.put("returnBoday", "FUCK");

            String encodedStr = UrlSafeBase64.encodeToString(jsonObject.toString());
            String sign = hmacDigest(encodedStr, SECRET_KEY, HMAC_SHA1_ALGORITHM);
            String token = ACCESS_KEY + ":" + sign + ":" + encodedStr;
            uploadManager.put(data, UserInfo.getUserId(), token,
                    new UpCompletionHandler() {
                        @Override
                        public void complete(String key, ResponseInfo info, JSONObject res) {
                            if (info.isOK())
                                callback.onSuccess();
                            else
                                callback.onFail();
                            LogUtil.f(res.toString()+info.toString());
                        }
                    }, new UploadOptions(null, null, false, new UpProgressHandler() {
                        @Override
                        public void progress(String key, double percent) {
                            callback.onProgress(percent);
                        }
                    }, null));
        } catch (JSONException e) {
            callback.onFail();
            e.printStackTrace();
            LogUtil.f(e.getStackTrace().toString());
        }
    }

    public static void downloadDbFile(String filePath, Callback callback) {
        String url = "http://o949rog8m.bkt.clouddn.com/" + UserInfo.getUserId();
        url += "?e=" + (System.currentTimeMillis() / 1000 + 600);
        String sign = hmacDigest(url, SECRET_KEY, HMAC_SHA1_ALGORITHM);
        String token = ACCESS_KEY + ":" + sign;
        url += "&token=" + token;
        download(url, filePath, callback);
    }

    private static void download(final String url, final String filePath, final Callback callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                String suffix = ".tmp";
                FileOutputStream fos = null;
                try {
                    URL u = new URL(url);
                    HttpURLConnection connection = (HttpURLConnection) u.openConnection();
                    connection.setReadTimeout(3000);
                    connection.setDoInput(true);
                    connection.setDoOutput(false);
                    connection.setConnectTimeout(10000);
                    InputStream is = connection.getInputStream();
                    File tmpFile = new File(filePath + suffix);
                    fos = new FileOutputStream(tmpFile);
                    byte[] buffer = new byte[2048];
                    int n = 0;
                    do {
                        Thread.yield();
                        fos.write(buffer, 0, n);
                        n = is.read(buffer);
                    } while (n != -1);
                    fos.close();
                    tmpFile.renameTo(new File(filePath));
                    callback.onSuccess();
                } catch (Exception e) {
                    callback.onFail();
                } finally {
                    new File(filePath + suffix).delete();

                }
            }
        }).start();
    }

    public interface Callback {
        void onSuccess();

        void onFail();

        void onProgress(double percentage);
    }
}
